namespace pengpeng
{
	export class PPBox2D {
		private bd:Box2D.Dynamics.b2BodyDef;
		private fd:Box2D.Dynamics.b2FixtureDef;

		public constructor() {
			this.bd = new Box2D.Dynamics.b2BodyDef();
			this.fd = new Box2D.Dynamics.b2FixtureDef();
		}

		private static _instance:PPBox2D;
		public static get instance():PPBox2D
		{
			if(PPBox2D._instance == null)
			{
				PPBox2D._instance = new PPBox2D();
			}
			return PPBox2D._instance;
		}
		public buildWorld(worldData:WorldData):Box2D.Dynamics.b2World
		{
			if(worldData == null)
			{
				return null;
			}
			var world:Box2D.Dynamics.b2World;

			let gravity:Box2D.Common.Math.b2Vec2 = new Box2D.Common.Math.b2Vec2(worldData.gravity.x, worldData.gravity.y);
			let doSleep:boolean = true;
			world = new Box2D.Dynamics.b2World(gravity, doSleep);

			let i:number;
			let len:number;
			for(i = 0, len = worldData.bodies.length; i < len; i++)
			{
				this.buildBody(worldData.bodies[i],world);
			}
			return world;
		}

		protected buildBody(bodyData:BodyData, world:Box2D.Dynamics.b2World):Box2D.Dynamics.b2Body
		{
			var body:Box2D.Dynamics.b2Body;
			let fixtureData:MaterialData = bodyData.materialData;
			let shapeData:ShapeData = bodyData.shapeData;

			this.bd.position.Set(bodyData.x,bodyData.y);
			switch(bodyData.type)
			{
				case BodyData.TYPE_DYNAMIC:
					this.bd.type = Box2D.Dynamics.b2Body.b2_dynamicBody;
					break;
				case BodyData.KINEMATIC:
					this.bd.type = Box2D.Dynamics.b2Body.b2_kinematicBody;
					break;
				case BodyData.TYPE_STATIC:
				default:
					this.bd.type = Box2D.Dynamics.b2Body.b2_staticBody;
					break;
			}
			
			this.fd.density = fixtureData.density;
			this.fd.friction = fixtureData.friction;
			this.fd.restitution = fixtureData.restitution;
			this.fd.shape = this.buildShape(shapeData);
			body = world.CreateBody(this.bd);
			body.CreateFixture(this.fd);
			body.SetUserData(bodyData.name);
			return body;
		}
		protected buildShape(shapeData:ShapeData):Box2D.Collision.Shapes.b2Shape
		{
			let shape:Box2D.Collision.Shapes.b2Shape;
			switch(shapeData.type)
			{
				case ShapeData.CIRCLE:
					shape = new Box2D.Collision.Shapes.b2CircleShape(shapeData.radius);
					break;
				case ShapeData.RECTANGLE:
					shape = Box2D.Collision.Shapes.b2PolygonShape.AsBox(shapeData.width, shapeData.height);
					break;
				case ShapeData.POLGON:
					break;
			}
			return shape;
		}
	}
}
